<template>
	<div>
		<div v-for="(item, index) of treeNodes" :key="index" style="width: 300px">
			<div class="itemTitle border-bottom" style="margin-top: 10px; cursor: pointer">
				<!-- <el-checkbox v-if="treeAttr.isCheckBox" v-model="item.isChecked" @change="changeCheck(item, item.isChecked)" /> -->
				<el-icon><FolderOpened /></el-icon>
				<span :class="item.isSelected ? 'color2' : 'color1'" @click="onSelectNode(item)">
					{{ item.Title }}
				</span>
				<el-icon v-if="item.canDelete" style="margin-left: 3px; color: red" @click="onDelNode(item)"><Delete /></el-icon>
				<el-icon v-if="item.canAddChild" class="el-icon-plus" style="margin-left: 3px; color: #67c23a" @click="onAddNode(item)"><Plus /></el-icon>
				<el-icon v-if="item.canUpdate" class="el-icon-edit-outline" style="margin-left: 3px; color: #409eff" @click="onUpdateNode(item)"
					><Edit
				/></el-icon>
			</div>
			<!-- 当数据中有Child属性时，对组件本身进行循环递归 -->
			<div v-if="item.Child" class="itemChild">
				<DetailList :tree-attr="treeAttr" :nodes="item.Child" :in-root-nodes="rootNodes" :events="events" />
			</div>
		</div>
	</div>
</template>

<script lang="js">
// 组件使用方法
// 节点中必须包含: Code(节点编码), Title(节点标题), Child(子节点), canDelete(该节点是否能被删除), canAddChild(该节点是否能增加子节点), canUpdate(该节点是否能被修改)
// 节点中间会产生新数据: isChecked(节点是否被勾选), isSelected(节点是否被选中)
// 输入参数：events:回调函数: loadTree(加载树函数，同步函数) onSelected(选中), onChecked(勾选), onAddNode(添加子节点), onUpdateNode(修改), onDelNode(删除)
//          treeAttr: treeKey: 树的key值, isCheckBox: 是否有勾选框
//          nodes: 当前递归时的节点列表, 内部数据，调用者不用传该参数
//          inRootNodes: 树的根节点列表, 内部数据，调用者不用传该参数
export default {
	name: 'DetailList',
	props: {
		events: {
			type: Object,
			default: () => {
				return {
					loadTree: null,
					onSelected: null,
					onChecked: null,
					onAddNode: null,
					onUpdateNode: null,
					onDelNode: null
				}
			}
		},
		topNode: {
			type: Array,
			default: () => []
		},
		treeAttr: {
			type: Object,
			default: () => {
				return { treeKey: -1, isEdit: false, isCheckBox: true }
			}
		},
		nodes: { type: Array, default: null },
		inRootNodes: { type: Array, default: null }
	},
	data() {
		return {
			treeNodes: [],
			rootNodes: null,
			selectedNode: null,
			changecolor: 0
		}
	},
	async created() {
		if (this.inRootNodes === null) {
			if (this.events.loadTree === null) {
				console.error('[Error]Failed to load tree, the load func is null.')
				return
			}
			this.treeNodes = []
			const funcTree = await this.events.loadTree(this.treeAttr.treeKey)
			// if (this.topNode.length) {
			// 	this.treeNodes.push(this.topNode)
			// }
			if (funcTree === null) {
				console.log('[Debug]Tree is empty.')
				return
			}
			this.rootNodes = []
			this.rootNodes.push(funcTree)
			this.treeNodes.push(funcTree)
		} else {
			this.treeNodes = this.nodes
			this.rootNodes = this.inRootNodes
		}
	},
	methods: {
		refreshTree(parentNodes) {
			if (!parentNodes) {
				parentNodes = this.treeNodes
			}
			parentNodes.splice(0, 0)

			for (let i = 0; i < parentNodes.length; i++) {
				if (parentNodes[i].Child && parentNodes[i].Child.length > 0) {
					this.refreshTree(parentNodes[i].Child)
				}
			}
		},
		async reloadTree(reloadNodeCode) {
			console.log('[Debug]Reload tree node: ', reloadNodeCode)
			if (this.events.loadTree === null) {
				console.error('[Debug]Failed to load tree, the load func is null.')
				return
			}

			const funcTree = await this.events.loadTree(this.treeAttr.treeKey)
			if (!funcTree) {
				console.log('[Debug]Tree is empty.')
				return
			}

			if (!reloadNodeCode || reloadNodeCode === '') {
				this.rootNodes.splice(0, this.rootNodes.length)
				this.rootNodes.push(funcTree)
				this.treeNodes.splice(0, this.rootNodes.length)
				this.treeNodes.push(funcTree)
				this.refreshTree()
				console.log('[Debug]Tree reloaded: ', this.rootNodes)
				return
			}
			// 在新的树中查找需要重新加载的节点
			const node = this._getNode(funcTree, reloadNodeCode)
			if (node === null) {
				console.error('[Error]Reload tree fail, the node is not exist, node code: ', reloadNodeCode)
				return
			}
			console.log('000000000000: ', node)
			if (!node.ParentCode || node.ParentCode === '') {
				// 刷新顶级节点
				this.rootNodes.splice(0, this.rootNodes.length)
				this.rootNodes.push(funcTree)
				this.treeNodes.splice(0, this.rootNodes.length)
				this.treeNodes.push(funcTree)
				this.refreshTree()
				console.log('[Debug]Tree reloaded2: ', this.rootNodes)
				return
			}
			// 在目前的树中查找其父节点
			const parentNode = this.getNode(node.ParentCode)
			if (parentNode === null) {
				console.error('[Error]Reload tree fail, the parent node is not exist, code: ', node.ParentCode)
				return
			}
			this.replaceNode(parentNode, node)
			if (this.events.onSelected) {
				this.events.onSelected(node)
			}
			console.log('[Debug]Tree node reloaded: ', parentNode, node)
		},
		cancelSelect(parentNodes) {
			if (!parentNodes) {
				parentNodes = this.rootNodes
			}
			for (let i = 0; i < parentNodes.length; i++) {
				if (parentNodes[i].isSelected) {
					parentNodes[i].isSelected = false
					parentNodes.splice(0, 0)
					return
				}
			}

			for (let i = 0; i < parentNodes.length; i++) {
				if (parentNodes[i].Child && parentNodes[i].Child.length > 0) {
					this.cancelSelect(parentNodes[i].Child)
				}
			}
		},
		selectNode(node) {
			this.cancelSelect(this.rootNodes)
			this.selectedNode = node
			this.selectedNode.isSelected = true
			this.treeNodes.splice(0, 0)
		},
		replaceNode(parentNode, node) {
			if (!parentNode || !node) {
				console.log('[Debug][TreeFunc]Parent node or node is null: ', parentNode, node)
				return
			}
			if (!parentNode.Child) {
				parentNode.Child = []
				parentNode.Child.push(node)
				this.refreshTree()
				return
			}

			for (let i = 0; i < parentNode.Child.length; i++) {
				if (parentNode.Child[i].Code === node.Code) {
					const isSelected = parentNode.Child[i].isSelected
					parentNode.Child[i] = node
					if (isSelected !== undefined) {
						parentNode.Child[i].isSelected = isSelected
					}
					parentNode.Child.splice(0, 0)
					console.log('[Debug][TreeFunc]Node is replaced: ', parentNode, node)
					return
				}
			}
			// 没找到就新增
			parentNode.Child.push(node)
			console.log('[Debug][TreeFunc]Node is added: ', parentNode, node)
		},
		delNode(node) {
			console.log('[Debug[TreeItem]Delete node: ', node)
			if (!node.ParentCode || node.ParentCode === '') {
				this.$message({ type: 'error', message: '顶级节点不能删除' })
				return
			}

			if (!this.treeNodes || this.treeNodes.length === 0) {
				return
			}

			if (node.Child && node.Child.length > 0) {
				this.$message({ type: 'error', message: '该有子节点，请先删除子节点' })
				return
			}
			for (let i = 0; i < this.treeNodes.length; i++) {
				this._delNode(this.treeNodes[i], node)
			}
		},
		_delNode(tree, node) {
			const parentNode = this._getNode(tree, node.ParentCode)
			if (parentNode === null || !parentNode.Child) {
				return
			}
			for (let i = 0; i < parentNode.Child.length; i++) {
				if (node.Code === parentNode.Child[i].Code) {
					parentNode.Child.splice(i, 1)
					return
				}
			}
		},
		changeCheck(item, isChecked) {
			item.isChecked = isChecked
			if (item.Child) {
				for (let i = 0; i < item.Child.length; i++) {
					this.changeCheck(item.Child[i], isChecked)
				}
				item.Child.splice(0, 0)
			}
		},
		getNode(code) {
			if (!code || code === '') {
				if (this.treeNodes.length > 0) {
					return this.treeNodes[0]
				} else {
					return null
				}
			}

			if (!this.treeNodes || this.treeNodes.length === 0) {
				return null
			}
			for (let i = 0; i < this.treeNodes.length; i++) {
				const node = this._getNode(this.treeNodes[i], code)
				if (node !== null) {
					return node
				}
			}
			console.log('find node fail: ', this.treeNodes, code)
			return null
		},
		_getNode(tree, code) {
			if (tree.Code === code) {
				return tree
			}
			if (!tree.Child) {
				return null
			}

			for (let i = 0; i < tree.Child.length; i++) {
				const node = this._getNode(tree.Child[i], code)
				if (node !== null) {
					return node
				}
			}
			return null
		},
		onAddNode(node) {
			this.selectNode(node)
			if (this.events.onAddNode) {
				this.events.onAddNode(node)
			}
			this.refreshTree(this.rootNodes)
		},
		onUpdateNode(node) {
			this.selectNode(node)
			if (this.events.onUpdateNode) {
				this.events.onUpdateNode(node)
			}
			this.refreshTree(this.rootNodes)
		},
		onDelNode(node) {
			this.selectNode(node)
			if (this.events.onDelNode) {
				this.events.onDelNode(node)
			}
			this.refreshTree(this.rootNodes)
		},
		onSelectNode(node) {
			this.selectNode(node)
			if (this.events.onSelected) {
				this.events.onSelected(node)
			}
			this.refreshTree(this.rootNodes)
		}
	}
}
</script>

<style scoped>
.itemTitle {
	/* line-height: 5px; */
	font-size: 18px;
	padding: 0 10px;
	display: flex;
	align-items: center;
}
.itemTitle:hover {
	background: #ccc;
}

.itemChild {
	padding: 0 15px;
}

.color2 {
	color: rgb(0, 38, 255);
}
</style>
